package com.gitee.wsl.doc.prosemirror.ui.command

import com.gitee.wsl.doc.prosemirror.state.Command
import com.gitee.wsl.doc.prosemirror.state.CommandDispatch
import com.gitee.wsl.doc.prosemirror.state.EditorState
import com.gitee.wsl.doc.prosemirror.ui.EditorView
import com.gitee.wsl.func.plus

fun interface UiCommand: Command {
    fun exec(view: EditorView?, state: EditorState, dispatch: CommandDispatch?):Boolean

    override fun exec(state: EditorState, dispatch: CommandDispatch?): Boolean = exec(null, state = state,dispatch)
}

fun UiCommand.toCommand(view: EditorView) = object:AbstractEditorViewCommand(view){
    override fun exec(
        state: EditorState,
        dispatch:CommandDispatch?,
    ): Boolean = exec(view,state,dispatch)
}

fun Command.toUiCommand() = UiCommand{view, state, function ->
    this@toUiCommand.exec(state,function)
}

operator fun UiCommand.plus(other:CommandDispatch) = UiCommand{ view,state, function ->
    this@plus.exec(view,state,function + other)
}

/// Combine a number of command functions into a single function (which
/// calls them one by one until one returns true).
fun chainCommands(vararg commands: UiCommand): UiCommand {
    return UiCommand { view,state,dispatch->
        commands.forEach {
            if(it.exec(view,state,dispatch)) return@UiCommand true
        }
        return@UiCommand false
    }
}

operator fun UiCommand.plus(other:Command) = chainCommands(this,other.toUiCommand())

operator fun Command.plus(other:UiCommand) = chainCommands(this.toUiCommand(),other)